
module LINF_CLKRCV(
   input                            LINF_RESET,
   input                            RFCLK_CLOCK155,
   input[15:0]                      OVSMP_IN_DATA,

   output[7:0]                      RCV_OUT_DATA,
   output                           RCV_OUT_DATA_EN,

   input                            GLBCF_LINF_MODE
   ) ;

reg                              MDSEL_MODE;
reg[1:0]                         MDSEL_CNT4;
reg[15:4]                        MDSEL_STM1_DATA;
reg[15:0]                        MDSEL_OUT_DATA;
reg                              MDSEL_OUT_DEN;


reg[15:0]                        EDECT_OVSAMPLE_DATA;
reg                              EDECT_OVSAMPLE_DEN;
reg                              EDECT_EDGE_0, EDECT_EDGE_1, EDECT_EDGE_2, EDECT_EDGE_3;
reg[3:0]                         EDECT_OUT_EDGE;
reg[15:0]                        EDECT_OUT_OVSAMPLE_DATA;
reg                              EDECT_OUT_DEN;

reg[15:0]                        DSEL_OVSMP_DATA;
reg[2:0]                         DSEL_EDGE_PNT;
reg[1:0]                         DSEL_SAMPLE_PNT;
reg[4:0]                         DSEL_OUT_DATA;
reg[2:0]                         DSEL_OUT_BIT_CNT;
wire                             DSEL_OUT_DEN;


reg[4:0]                         ALBYTE_WPNT;
reg[31:0]                        ALBYTE_REGS_ARRAY;
reg[7:0]                         ALBYTE_WS_BYTE;
reg[15:0]                        ALBYTE_WDIN16 ;
reg                              ALBYTE_NBEN;
reg[7:0]                         ALBYTE_NB_DATA_BYTE;


always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 )
      MDSEL_MODE                                     <= 1'b0;
   else
      MDSEL_MODE                                     <= GLBCF_LINF_MODE;
end

always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 )
      MDSEL_CNT4[1:0]                                <= 2'd0;
   else
      MDSEL_CNT4[1:0]                                <= MDSEL_CNT4[1:0] + 2'd1;
end

always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 )
      MDSEL_STM1_DATA[15:4]                          <= 12'd0;
   else begin
      case ( MDSEL_CNT4[1:0] )
      2'h0: MDSEL_STM1_DATA[15:12]                   <= {OVSMP_IN_DATA[15], OVSMP_IN_DATA[11], OVSMP_IN_DATA[7], OVSMP_IN_DATA[3]};
      2'h1: MDSEL_STM1_DATA[11:8]                    <= {OVSMP_IN_DATA[15], OVSMP_IN_DATA[11], OVSMP_IN_DATA[7], OVSMP_IN_DATA[3]};
      2'h2: MDSEL_STM1_DATA[7:4]                     <= {OVSMP_IN_DATA[15], OVSMP_IN_DATA[11], OVSMP_IN_DATA[7], OVSMP_IN_DATA[3]};
      default: ;
      endcase
   end
end

always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 ) begin
      MDSEL_OUT_DATA[15:0]                      <= 16'd0;
      MDSEL_OUT_DEN                             <= 1'b0;
   end
   else begin
      if ( MDSEL_MODE==1'b1 ) begin
         MDSEL_OUT_DATA[15:0]                   <= OVSMP_IN_DATA[15:0];
         MDSEL_OUT_DEN                          <= 1'b1;
      end
      else begin
         if ( MDSEL_CNT4==2'd3 ) begin
            MDSEL_OUT_DATA[15:4]               <= MDSEL_STM1_DATA[15:4];
            MDSEL_OUT_DATA[3]                   <= OVSMP_IN_DATA[15];
            MDSEL_OUT_DATA[2]                   <= OVSMP_IN_DATA[11];
            MDSEL_OUT_DATA[1]                   <= OVSMP_IN_DATA[7];
            MDSEL_OUT_DATA[0]                   <= OVSMP_IN_DATA[3];
            MDSEL_OUT_DEN                       <= 1'b1;
         end
         else begin
            MDSEL_OUT_DEN                       <= 1'b0;
         end
      end
   end
end


always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 ) begin
      EDECT_OVSAMPLE_DATA[15:0]                 <= 16'h0000;
      EDECT_OVSAMPLE_DEN                        <= 1'b0;
   end
   else begin
      EDECT_OVSAMPLE_DATA[15:0]                 <= MDSEL_OUT_DATA[15:0];
      EDECT_OVSAMPLE_DEN                        <= MDSEL_OUT_DEN;
   end
end



always @( EDECT_OVSAMPLE_DATA)  begin
    if ( EDECT_OVSAMPLE_DATA[15:10]==6'b000_111 /*|| EDECT_OVSAMPLE_DATA[15:10]==6'b111_0000*/)
        EDECT_EDGE_0                            <= 1'b1;
    else
        EDECT_EDGE_0                            <= 1'b0;
end
always @( EDECT_OVSAMPLE_DATA)  begin
    if ( EDECT_OVSAMPLE_DATA[14:9]==6'b000_111 /*|| EDECT_OVSAMPLE_DATA[14:9]==6'b111_000*/)
        EDECT_EDGE_1                            <= 1'b1;
    else
        EDECT_EDGE_1                            <= 1'b0;
end
always @( EDECT_OVSAMPLE_DATA)  begin
    if ( EDECT_OVSAMPLE_DATA[13:8]==6'b000_111 /*|| EDECT_OVSAMPLE_DATA[13:8]==6'b111_000*/)
        EDECT_EDGE_2                            <= 1'b1;
    else
        EDECT_EDGE_2                            <= 1'b0;
end
always @( EDECT_OVSAMPLE_DATA)  begin
    if ( EDECT_OVSAMPLE_DATA[12:7]==6'b000_111 /*|| EDECT_OVSAMPLE_DATA[12:7]==6'b111_000*/)
        EDECT_EDGE_3                            <= 1'b1;
    else
        EDECT_EDGE_3                            <= 1'b0;
end


// check available position from input data
always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 ) begin
      EDECT_OUT_EDGE[3:0]                       <= 4'b0000;
      EDECT_OUT_OVSAMPLE_DATA[15:0]             <= 16'd0;
      EDECT_OUT_DEN                             <= 1'b0;
   end
   else begin
      EDECT_OUT_EDGE[3:0]                       <= {EDECT_EDGE_0, EDECT_EDGE_1, EDECT_EDGE_2, EDECT_EDGE_3};
      EDECT_OUT_OVSAMPLE_DATA[15:0]             <= EDECT_OVSAMPLE_DATA[15:0];
      EDECT_OUT_DEN                             <= EDECT_OVSAMPLE_DEN;
   end
end




always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 ) begin
      DSEL_OVSMP_DATA[15:0]                     <= 16'd0;
   end
   else if ( EDECT_OUT_DEN==1'b1 ) begin
      DSEL_OVSMP_DATA[15:0]                     <= EDECT_OUT_OVSAMPLE_DATA[15:0];
   end
end
always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 )
      DSEL_EDGE_PNT[2:0]                        <= 3'b111;
   else if ( EDECT_OUT_DEN==1'b1 ) begin
      case ( EDECT_OUT_EDGE[3:0] )
      4'b1000 : DSEL_EDGE_PNT[2:0]              <= 3'b001;
      4'b0100 : DSEL_EDGE_PNT[2:0]              <= 3'b010;
      4'b0010 : DSEL_EDGE_PNT[2:0]              <= 3'b011;
      4'b0001 : DSEL_EDGE_PNT[2:0]              <= 3'b000;
      default : DSEL_EDGE_PNT[2:0]              <= 3'b111;
      endcase
   end
end
always @(posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 )
      DSEL_SAMPLE_PNT[1:0]                              <= 2'd0;
   else if( EDECT_OUT_DEN==1'b1 ) begin
      if ( DSEL_EDGE_PNT[2:0]!=3'b111 )
         DSEL_SAMPLE_PNT[1:0]                           <= DSEL_EDGE_PNT[1:0];
   end
end

  assign DSEL_OUT_DEN  = EDECT_OUT_DEN;
always @(posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
   if ( LINF_RESET==1'b1 ) begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd0;
         DSEL_OUT_DATA[4:0]                             <= 5'd0;
   end
   else begin
      if ( DSEL_SAMPLE_PNT[1:0]==2'd0 && DSEL_EDGE_PNT[2:0]==3'd3 ) begin       // data select position 0 move to 3, output 5 bit data
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd5;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[15];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[12];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[8];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[4];
         DSEL_OUT_DATA[0]                               <= DSEL_OVSMP_DATA[0];
      end
      else if ( DSEL_SAMPLE_PNT[1:0]==2'd3 && DSEL_EDGE_PNT[2:0]==3'd0 ) begin       // data select position 3 move to 0, output 5 bit data
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd3;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[12];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[8];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[4];
         DSEL_OUT_DATA[1]                               <= 1'b0;
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_EDGE_PNT[2:0]==3'd0 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[15];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[11];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[7];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[3];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_EDGE_PNT[2:0]==3'd1 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[14];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[10];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[6];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[2];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_EDGE_PNT[2:0]==3'd2 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[13];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[9];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[5];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[1];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_EDGE_PNT[2:0]==3'd3 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[12];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[8];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[4];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[0];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_SAMPLE_PNT[1:0]==2'd0 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[15];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[11];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[7];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[3];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_SAMPLE_PNT[1:0]==2'd1 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[14];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[10];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[6];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[2];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_SAMPLE_PNT[1:0]==2'd2 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[13];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[9];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[5];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[1];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else if ( DSEL_SAMPLE_PNT[1:0]==2'd3 )  begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= DSEL_OVSMP_DATA[12];
         DSEL_OUT_DATA[3]                               <= DSEL_OVSMP_DATA[8];
         DSEL_OUT_DATA[2]                               <= DSEL_OVSMP_DATA[4];
         DSEL_OUT_DATA[1]                               <= DSEL_OVSMP_DATA[0];
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
      else begin
         DSEL_OUT_BIT_CNT[2:0]                          <= 3'd4;
         DSEL_OUT_DATA[4]                               <= 1'b0;
         DSEL_OUT_DATA[3]                               <= 1'b0;
         DSEL_OUT_DATA[2]                               <= 1'b0;
         DSEL_OUT_DATA[1]                               <= 1'b0;
         DSEL_OUT_DATA[0]                               <= 1'b0;
      end
   end
end



always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
    if ( LINF_RESET==1'b1 )
        ALBYTE_WPNT[4:0]                                 <=5'b00000;
    else if ( DSEL_OUT_DEN==1'b1 ) begin
        case ( DSEL_OUT_BIT_CNT[2:0] )
        3'b011 : ALBYTE_WPNT[4:0]                        <=ALBYTE_WPNT[4:0] +5'd3;
        3'b100 : ALBYTE_WPNT[4:0]                        <=ALBYTE_WPNT[4:0] +5'd4;
        3'b101 : ALBYTE_WPNT[4:0]                        <=ALBYTE_WPNT[4:0] +5'd5;
        default: ALBYTE_WPNT[4:0]                        <=ALBYTE_WPNT[4:0] +5'd4;
        endcase
    end
end

always @( ALBYTE_WPNT or ALBYTE_REGS_ARRAY)  begin
    case ( ALBYTE_WPNT[4:3])
    2'b00  : ALBYTE_WS_BYTE[7:0]                         <=ALBYTE_REGS_ARRAY[7:0] ;
    2'b01  : ALBYTE_WS_BYTE[7:0]                         <=ALBYTE_REGS_ARRAY[15:8] ;
    2'b10  : ALBYTE_WS_BYTE[7:0]                         <=ALBYTE_REGS_ARRAY[23:16] ;
    2'b11  : ALBYTE_WS_BYTE[7:0]                         <=ALBYTE_REGS_ARRAY[31:24] ;
    endcase
end

always @( ALBYTE_WPNT or ALBYTE_WPNT or DSEL_OUT_DATA or ALBYTE_WS_BYTE)  begin
    case ( ALBYTE_WPNT[2:0] )
    3'b000 :  ALBYTE_WDIN16[15:0]                        <={DSEL_OUT_DATA[4:0] ,11'b00000000000} ;
    3'b001 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7] ,DSEL_OUT_DATA[4:0] ,10'b0000000000} ;
    3'b010 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7:6] ,DSEL_OUT_DATA[4:0] ,9'b000000000} ;
    3'b011 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7:5] ,DSEL_OUT_DATA[4:0] ,8'b00000000} ;
    3'b100 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7:4] ,DSEL_OUT_DATA[4:0] ,7'b0000000} ;
    3'b101 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7:3] ,DSEL_OUT_DATA[4:0] ,6'b000000} ;
    3'b110 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7:2] ,DSEL_OUT_DATA[4:0] ,5'b00000} ;
    3'b111 :  ALBYTE_WDIN16[15:0]                        <={ALBYTE_WS_BYTE[7:1] ,DSEL_OUT_DATA[4:0] ,4'b0000} ;
    endcase
end

always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
    if ( LINF_RESET==1'b1 )
        ALBYTE_REGS_ARRAY[31:0]                          <=32'h0000_0000 ;
    else if ( DSEL_OUT_DEN==1'b1 ) begin
        case ( ALBYTE_WPNT[4:3] )
        2'b00 :  ALBYTE_REGS_ARRAY[31:0]                 <={ ALBYTE_REGS_ARRAY[31:16] ,ALBYTE_WDIN16[7:0] ,ALBYTE_WDIN16[15:8] } ;
        2'b01 :  ALBYTE_REGS_ARRAY[31:0]                 <={ ALBYTE_REGS_ARRAY[31:24] ,ALBYTE_WDIN16[7:0] ,ALBYTE_WDIN16[15:8] ,ALBYTE_REGS_ARRAY[7:0] } ;
        2'b10 :  ALBYTE_REGS_ARRAY[31:0]                 <={ ALBYTE_WDIN16[7:0] ,ALBYTE_WDIN16[15:8] ,ALBYTE_REGS_ARRAY[15:0]} ;
        2'b11 :  ALBYTE_REGS_ARRAY[31:0]                 <={ ALBYTE_WDIN16[15:8] ,ALBYTE_REGS_ARRAY[23:8] ,ALBYTE_WDIN16[7:0]} ;
        endcase
    end
end

always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
    if ( LINF_RESET==1'b1 )
        ALBYTE_NBEN                                      <=1'b0 ;
    else begin
        case ( DSEL_OUT_BIT_CNT[2:0] )
        3'b011 :  begin
            if ( ALBYTE_WPNT[2:0]==7 || ALBYTE_WPNT[2:0]==6 || ALBYTE_WPNT[2:0]==5 )
                ALBYTE_NBEN                              <=DSEL_OUT_DEN;
            else
                ALBYTE_NBEN                              <=1'b0 ;
        end
        3'b100 :  begin
            if ( ALBYTE_WPNT[2:0]==7 || ALBYTE_WPNT[2:0]==6 || ALBYTE_WPNT[2:0]==5 || ALBYTE_WPNT[2:0]==4 )
                ALBYTE_NBEN                              <=DSEL_OUT_DEN;
            else
                ALBYTE_NBEN                              <=1'b0 ;
        end
        3'b101 :  begin
            if ( ALBYTE_WPNT[2:0]==7 || ALBYTE_WPNT[2:0]==6 || ALBYTE_WPNT[2:0]==5 || ALBYTE_WPNT[2:0]==4 || ALBYTE_WPNT[2:0]==3)
                ALBYTE_NBEN                              <=DSEL_OUT_DEN;
            else
                ALBYTE_NBEN                              <=1'b0 ;
        end
        default : ALBYTE_NBEN                            <=1'b0 ;
        endcase
    end
end
always @( posedge LINF_RESET or posedge RFCLK_CLOCK155)  begin
    if ( LINF_RESET==1'b1 )
        ALBYTE_NB_DATA_BYTE[7:0]                         <=8'b0000_0000 ;
    else begin
        case ( ALBYTE_WPNT[4:3])
        2'b00 : ALBYTE_NB_DATA_BYTE[7:0]                 <=ALBYTE_REGS_ARRAY[31:24] ;
        2'b01 : ALBYTE_NB_DATA_BYTE[7:0]                 <=ALBYTE_REGS_ARRAY[7:0] ;
        2'b10 : ALBYTE_NB_DATA_BYTE[7:0]                 <=ALBYTE_REGS_ARRAY[15:8] ;
        2'b11 : ALBYTE_NB_DATA_BYTE[7:0]                 <=ALBYTE_REGS_ARRAY[23:16] ;
        endcase
    end
end

assign RCV_OUT_DATA[7:0]              =ALBYTE_NB_DATA_BYTE[7:0] ;
assign RCV_OUT_DATA_EN                =ALBYTE_NBEN ;

endmodule

